package elven.codingit.easysearch.util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryparser.classic.MultiFieldQueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.FSDirectory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import elven.codingit.easysearch.model.dto.IndexSearchDto;
import elven.codingit.easysearch.model.dto.IndexerResult;

/**
 * indexer工具类
 * 开发lucene版本要求：5.5.0
 * 中文分词插件：JcsegAnalyzer5X
 * @author liuyy
 * @date 2016年8月26日
 */
public class IndexerSearch {
	
	private static IndexerSearch INDEXER_SEARCH = null;
	private static final Logger log = LoggerFactory.getLogger(IndexerSearch.class);
	
	private IndexerSearch() {}
	
	private static ThreadLocal<IndexerSearch> indexfactory = new ThreadLocal<IndexerSearch>(){
		@Override
		protected IndexerSearch initialValue() {
			if(INDEXER_SEARCH == null){
				INDEXER_SEARCH = new IndexerSearch();
			}
			return INDEXER_SEARCH;
		}
	};
	
	public static IndexerSearch getInstance(){
		return indexfactory.get();
	}
	
	/**
	 * 根据id精确查询
	 * @throws Exception
	 * @author liuyy
	 * @date 2016年8月30日
	 */
	public IndexerResult termIdQuery(IndexSearchDto searchDto)throws Exception{
		Term term = new Term("id", searchDto.getKeyword());
		Query query = new TermQuery(term);
		return search(searchDto, query);
	}
	
	/**
	 * @throws Exception
	 * @author liuyy
	 * @date 2016年8月30日
	 */
	public IndexerResult query(IndexSearchDto searchDto)throws Exception{
		//组合索引查询器
		Query query = new MultiFieldQueryParser(IndexWordHelper.getSavedKeys(), 
				IndexHelper.getInstance().configAnalyzer())
				.parse(searchDto.getKeyword());
		return search(searchDto, query);
	}
	
	/**
	 * search by query
	 * @throws Exception
	 * @author liuyy
	 * @date 2016年8月26日
	 */
	private IndexerResult search(IndexSearchDto searchDto, Query query) throws Exception{
		List<Map<String, Object>> results = new ArrayList<>();
		IndexerResult result = new IndexerResult();
		
		//search对象
		IndexSearcher isearcher = IndexHelper.getInstance().configSearch(searchDto.getFsDirectory());
	    TopDocs topDocs = isearcher.search(query, Integer.MAX_VALUE);
	    int count = topDocs.totalHits;
	    result.setCount(count);//查询结果总数
	    
	    ScoreDoc[] scoreDocs = topDocs.scoreDocs; 
	    //临时存储对象
	    Map<String, Object> data = null; Document targetDoc = null;
	    for(int i = searchDto.getStart(); i < count && i < searchDto.getEnd(); i++){
	    	data = new HashMap<>();
	    	targetDoc = isearcher.doc(scoreDocs[i].doc);
	    	for(String key : IndexWordHelper.getSavedKeys()){
	    		if(StringUtils.isNotBlank(targetDoc.get(key))){
	    			data.put(key, targetDoc.get(key));
	    		}
	    	}
	    	results.add(data);
	    }
	    result.setResult(results);
	    return result;
	}
	
	/**
	 * 搜索并分页
	 * @param searchDto
	 * @throws Exception
	 * @author liuyy
	 * @date 2016年8月30日
	 */
	public IndexerResult search(IndexSearchDto searchDto) throws Exception{
		
		List<Map<String, Object>> results = new ArrayList<>();
		IndexerResult result = new IndexerResult();

		Analyzer analyzer = IndexHelper.getInstance().configAnalyzer();
		searchDto.setKeyword(searchDto.getKeyword().trim()+"*");
		//组合索引查询器
		Query query = new MultiFieldQueryParser(IndexWordHelper.getSearchKeys(),analyzer).parse(searchDto.getKeyword());
		log.warn("{}", query.toString());
		FSDirectory directory = searchDto.getFsDirectory();
		IndexReader ireader = DirectoryReader.open(directory);
	    IndexSearcher isearcher = new IndexSearcher(ireader);//search对象
	    TopDocs topDocs = isearcher.search(query, Integer.MAX_VALUE);
	    int count = topDocs.totalHits;
	    result.setCount(count);//查询结果总数
	    
	    ScoreDoc[] scoreDocs = topDocs.scoreDocs; 
	    //临时存储对象
	    Map<String, Object> data = null; Document targetDoc = null;
	    for(int i = searchDto.getStart(); i < count && i < searchDto.getEnd(); i++){
	    	data = new HashMap<>();
	    	targetDoc = isearcher.doc(scoreDocs[i].doc);
	    	for(String key : IndexWordHelper.getSavedKeys()){
	    		if(StringUtils.isNotBlank(targetDoc.get(key))){
	    			data.put(key, targetDoc.get(key));
	    		}
	    	}
	    	results.add(data);
	    }
	    result.setResult(results);
	    directory.close();
	    ireader.close();
	    return result;
	}
	
}